home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / Palettes / HotShape / HotShape.m < prev    next >
Text File  |  1995-06-12  |  5KB  |  209 lines

  1. // HotShape.m
  2. // By Charles G. Fleming, Educational Computing Services, Allegheny College.
  3. // Copyright 1992 Allegheny College
  4. // You may freely copy, distribute and reuse this code. 
  5. // Allegheny College and the author disclaim any warranty of any kind, 
  6. // expressed or implied, as to its fitness for any particular use.
  7. // This work was partially supported by a grant from the Vira Heinz Endowment.
  8.  
  9. #import "HotShape.h"
  10. #import "HotPath.h"
  11. #import "SmallCell.h"
  12.  
  13. @implementation HotShape
  14.  
  15. - (const char *)getInspectorClassName
  16. {
  17.     return "HotShapeInspector";
  18. }    
  19.  
  20. // Scale the HotShape object so that it has unit length and height.
  21. // Give it a custom cell so that it can be resized to an arbitrarily small
  22. // size in InterfaceBuilder.  The default shape will be a diamond shape.
  23. - initFrame:(const NXRect *)frameRect
  24. {
  25.     SmallCell *smallCell;
  26.     
  27.     self = [super initFrame:frameRect];
  28.     
  29.     hotPathName = malloc(1);
  30.     visible = YES;
  31.     [self scale:bounds.size.width :bounds.size.height];
  32.  
  33.     smallCell = [[SmallCell allocFromZone:[self zone]] init];
  34.     [self setCell:smallCell];
  35.  
  36.     // Define the hot shape paths that will be used.
  37.     setHotPaths();
  38.     
  39.     tag = 0;
  40.     [self setHotPathName:"diamond"];
  41.  
  42.     [self setOpaque:NO];    
  43.     return self;
  44. }
  45.  
  46. - (BOOL)acceptsFirstMouse
  47. {
  48.     return YES;
  49. }
  50.     
  51. - drawSelf:(const NXRect *)rects :(int)rectCount
  52. {    
  53.     drawHotPath(hotPathName, visible);
  54.     return self;
  55. }    
  56.  
  57. - awake
  58. {
  59.     setHotPaths();
  60.     return self;
  61. }
  62.  
  63. - sizeTo:(NXCoord)width :(NXCoord)height
  64. {
  65.     [super sizeTo:width :height];
  66.     [self scale:bounds.size.width :bounds.size.height];
  67.     return self;
  68. }
  69.  
  70. - setHotPathName:(const char *)name
  71. {
  72.     free(hotPathName);
  73.     hotPathName = malloc(strlen(name) + 1);
  74.     strcpy(hotPathName, name);    
  75.     return self;
  76. }    
  77.  
  78. - (char *)hotPathName
  79. {
  80.     return hotPathName;
  81. }
  82.         
  83. - (BOOL)visible
  84. {
  85.     return visible;
  86. }
  87.  
  88. - setVisible:(BOOL)seeIt
  89. {
  90.     visible = seeIt;
  91.     return self;
  92. }    
  93.     
  94. - read:(NXTypedStream *)typedStream
  95. {
  96.     [super read:typedStream];
  97.     NXReadTypes(typedStream, "*s", &hotPathName, &visible);
  98.     return self;
  99. }        
  100.  
  101. - write:(NXTypedStream *)typedStream
  102. {
  103.     [super write:typedStream];
  104.     
  105.     NXWriteTypes(typedStream, "*s", &hotPathName, &visible);
  106.     return self;
  107. }
  108.  
  109. - mouseDown:(NXEvent *)theEvent
  110. {
  111.     SEL action;
  112.     NXEvent *nextEvent;
  113.     BOOL finished = NO, done = NO;    
  114.     int at;
  115.     NXPoint windowCoords = {theEvent->location.x, theEvent->location.y};
  116.     View *currentview, *currentSuperview;
  117.     List *subviewList;
  118.     
  119.     if([self inHotPath:windowCoords])
  120.     {
  121.         if([cell isEnabled])
  122.             while(!finished)
  123.             {
  124.                 nextEvent = [NXApp getNextEvent:NX_MOUSEUPMASK];
  125.                 if(nextEvent->type == NX_MOUSEUP)
  126.                 {
  127.                     windowCoords.x = nextEvent->location.x;
  128.                     windowCoords.y = nextEvent->location.y;                
  129.                     if([self inHotPath:windowCoords])
  130.                     {
  131.                         action = [cell action];
  132.                         if(action)
  133.                             [self sendAction:action to:[cell target]];
  134.                     }
  135.                     finished = YES;    
  136.                 }
  137.             }
  138.     }        
  139.     else
  140.     {
  141.         // Pass on to the location to lower hotshape;
  142.         currentview = self;
  143.         currentSuperview = superview;
  144.         while(currentSuperview && !done)
  145.         {
  146.             subviewList = [currentSuperview subviews];
  147.             at = [subviewList indexOf:currentview] - 1;
  148.             done = [self traverseTreeWithRoot:currentSuperview startAt:at
  149.                     usingLocation:windowCoords];
  150.             currentview = currentSuperview;
  151.             currentSuperview = [currentSuperview superview];
  152.         }        
  153.     }
  154.     return self;    
  155. }
  156.  
  157. // Traverse a view's subview hierarchy, starting at the specified node,
  158. // until we get to the front-most hotshape.  If specified location is in
  159. // the hot path of the front-most hotshape we return YES.  In all other
  160. // cases we return NO.
  161. - (BOOL)traverseTreeWithRoot:root startAt:(int)at         
  162.         usingLocation:(NXPoint)windowCoords
  163. {
  164.     SEL action;
  165.     BOOL flag = NO;
  166.     List *subviewList;
  167.     int index;
  168.     id node;
  169.     SmallCell *smallCell;
  170.  
  171.     subviewList = [root subviews];
  172.     for(index = at; index > -1 && !flag; index--)
  173.     {
  174.         node = [subviewList objectAt:index];
  175.         if([node subviews])
  176.             flag = [self traverseTreeWithRoot:node 
  177.                     startAt:[[node subviews] count]-1
  178.                     usingLocation:windowCoords];
  179.         else
  180.             if([node isKindOf:[HotShape class]])
  181.             {
  182.                 flag = [node inHotPath:windowCoords];
  183.                 if(flag)
  184.                 {
  185.                     smallCell = [node cell];
  186.                     action = [smallCell action];
  187.                     if(action)
  188.                         [node sendAction:action to:[smallCell target]];
  189.                 }
  190.             }                
  191.     }
  192.  
  193.     return flag;
  194. }
  195.  
  196. // Determines if a point (given in window coords) is in the hot path.
  197. - (BOOL)inHotPath:(NXPoint)location
  198. {
  199.     NXPoint viewCoords = {location.x, location.y};
  200.     int inRegion = NO;
  201.  
  202.     [self convertPoint:&viewCoords fromView:nil];
  203.     [self lockFocus];    
  204.     inHotRegion(hotPathName, viewCoords.x, viewCoords.y, &inRegion);
  205.     [self unlockFocus];    
  206.     return inRegion;
  207. }                            
  208. @end
  209.